use std::fs;

use tree_sitter::{Parser, TreeCursor};
use walkdir::WalkDir;

// 根据接口的全路径搜索实现类的全路径
// todo 目前搜索import {packageName}
pub fn by_interface_name(project_path: &str, interface_name: &str) -> Vec<String> {
    if let Some(class_name) = interface_name.split('.').last() {
        // java 解析器
        let mut parser = Parser::new();
        parser
            .set_language(&tree_sitter_java::LANGUAGE.into())
            .expect("tree_sitter_sequel init fail");

        let contents: Vec<String> = WalkDir::new(project_path)
            .sort_by_file_name()
            .follow_links(true)
            .into_iter()
            .flat_map(|entry| {
                if let Ok(path) = entry {
                    let full_path: String = path.path().display().to_string();
                    if full_path.ends_with(".java") {
                        if let Ok(file_content) = fs::read_to_string(&full_path) {
                            // 解析
                            let node_tree = parser.parse(file_content.as_str(), None).unwrap();

                            // 查找package
                            let mut node_cursor = node_tree.walk();

                            // 查找imports
                            let imports = super::base::get_import(&mut node_cursor, &file_content);
                            let has_import = imports
                                .iter()
                                .any(|e| e == &format!("import {};", interface_name));

                            // 查找指定类
                            if has_import {
                                if let Some(package) =
                                    super::base::get_package_name(&mut node_cursor, &file_content)
                                {
                                    let interfaces: Vec<String> = get_class_name_by_implements(
                                        class_name,
                                        &mut node_tree.walk(),
                                        &file_content,
                                    );
                                    return interfaces
                                        .iter()
                                        .map(|short_name| format!("{}.{}", package, short_name))
                                        .collect();
                                }
                            }

                            return vec![];
                        }
                    }
                }
                return vec![];
            })
            .collect();
        return contents;
    }
    return vec![];
}

pub fn get_class_name_by_implements(
    interface_name: &str,
    node_cursor: &mut TreeCursor,
    source_code: &str,
) -> Vec<String> {
    let mut result: Vec<String> = vec![];
    let mut last_class_name: Option<String> = None;
    loop {
        let current_node = node_cursor.node();
        // 保存最近一次的类名
        if current_node.kind() == "class" {
            if node_cursor.goto_next_sibling() {
                let class_name_node = node_cursor.node();
                if class_name_node.kind() == "identifier" {
                    last_class_name = Some(
                        source_code[class_name_node.start_byte()..class_name_node.end_byte()]
                            .to_string(),
                    );
                }
            }
        }
        // 匹配到接口
        if current_node.kind() == "implements" {
            // 查找实现的接口
            node_cursor.goto_next_sibling();
            let type_identifier: Vec<String> =
                super::base::by_node_type("type_identifier", node_cursor, &source_code);
            let implements_interface = type_identifier
                .iter()
                .any(|item| item.as_str() == interface_name);
            if implements_interface {
                if let Some(last_class_name_content) = last_class_name.clone() {
                    result.push(last_class_name_content.to_string());
                }
            }
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            if !node_cursor.goto_parent() {
                return result;
            }
        }
    }
}
